// Centralized schema definitions and basic validation rules for Import/Export V2

const SCHEMA = {
  Dishes: [
    'dish_sku',
    'dish_slug',
    'name_zh',
    'name_en',
    'category',
    'base_status',
    'description_zh',
    'description_en',
    'ingredients_zh',
    'ingredients_en',
    'tags',
    'popularity'
  ],
  Variants: [
    'dish_sku',
    'name_zh',
    'variant_code',
    'variant_name',
    'price',
    'compare_at_price',
    'is_default',
    'stock'
  ],
  Options: [
    'dish_sku',
    'name_zh',
    'group_code',
    'group_name',
    'required',
    'value_code',
    'value_name',
    'price_delta'
  ]
};

const RULES = {
  // Per-field constraints (string lengths, enums, numeric ranges)
  Dishes: {
    dish_sku: { required: true, max: 64 },
    dish_slug: { required: true, max: 64, pattern: /^[a-z0-9-]+$/ },
    name_zh: { required: true, max: 100 },
    name_en: { required: true, max: 100 },
    category: { required: true, max: 50 },
    base_status: { required: true, enum: ['active', 'inactive'] },
    description_zh: { required: false, max: 2000 },
    description_en: { required: false, max: 2000 },
    ingredients_zh: { required: false, max: 1000 },
    ingredients_en: { required: false, max: 1000 },
    tags: { required: false, max: 255 },
    popularity: { required: false, int: true, min: 0, max: 100 }
  },
  Variants: {
    dish_sku: { required: true },
    name_zh: { required: false, max: 100 },
    variant_code: { required: true, max: 64 },
    variant_name: { required: true, max: 100 },
    price: { required: false, number: true, min: 0 },
    compare_at_price: { required: false, number: true, min: 0 },
    is_default: { required: false, boolean: true },
    stock: { required: false, int: true, min: 0 }
  },
  Options: {
    dish_sku: { required: true },
    name_zh: { required: false, max: 100 },
    group_code: { required: true, max: 64 },
    group_name: { required: true, max: 100 },
    required: { required: false, boolean: true },
    value_code: { required: true, max: 64 },
    value_name: { required: true, max: 100 },
    price_delta: { required: false, number: true } // can be negative
  }
};

function exactHeaderMatch(sheetName, actual) {
  const expected = SCHEMA[sheetName];
  const result = { match: true, missing: [], unexpected: [], order_diff: [] };
  if (!expected) return { match: false, missing: [], unexpected: actual, order_diff: expected || [] };
  // Check length equality
  if (actual.length !== expected.length) {
    result.match = false;
  }
  // Missing and unexpected
  const expSet = new Set(expected);
  const actSet = new Set(actual);
  for (const col of expected) if (!actSet.has(col)) { result.match = false; result.missing.push(col); }
  for (const col of actual) if (!expSet.has(col)) { result.match = false; result.unexpected.push(col); }
  // Order
  for (let i = 0; i < Math.min(actual.length, expected.length); i++) {
    if (actual[i] !== expected[i]) {
      result.match = false;
      result.order_diff.push({ index: i + 1, expected: expected[i], actual: actual[i] });
    }
  }
  return result;
}

function slugify(input) {
  const base = String(input || '').toLowerCase()
    .normalize('NFKD').replace(/[\u0300-\u036f]/g, '')
    .replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '-')
    .replace(/-{2,}/g, '-');
  return base.slice(0, 64);
}

function parseBoolean(val) {
  if (val === null || val === undefined || val === '') return undefined;
  const s = String(val).trim().toLowerCase();
  if (['true','1','yes','y'].includes(s)) return true;
  if (['false','0','no','n'].includes(s)) return false;
  return undefined; // invalid
}

// ===== Normalization configuration =====
const POPULARITY_LABEL_MAP = {
  'hot': 90,
  '热门': 90,
  'normal': 50,
  '一般': 50,
  'new': 70,
  '新品': 70
};

function normalizeBaseStatus(input) {
  const s = String(input ?? '').trim().toLowerCase();
  // 空值不再默认 active，按新规则视为非法，由校验阶段报错
  if (!s) return null;
  if (['active','inactive'].includes(s)) return s;
  if (['on','true','1','上架'].includes(s)) return 'active';
  if (['off','false','0','下架'].includes(s)) return 'inactive';
  return null; // cannot determine
}

function normalizePopularity(input) {
  if (input === null || input === undefined || String(input).trim() === '') return { value: null, mapped: false };
  const s = String(input).trim();
  if (/^\d+$/.test(s)) {
    const n = parseInt(s, 10);
    return { value: Number.isInteger(n) ? n : null, mapped: false };
  }
  const lowered = s.toLowerCase();
  if (Object.prototype.hasOwnProperty.call(POPULARITY_LABEL_MAP, lowered)) {
    return { value: POPULARITY_LABEL_MAP[lowered], mapped: true };
  }
  // try exact (e.g., 中文已在 map 中), fallback to original
  if (Object.prototype.hasOwnProperty.call(POPULARITY_LABEL_MAP, s)) {
    return { value: POPULARITY_LABEL_MAP[s], mapped: true };
  }
  return { value: NaN, mapped: false };
}

module.exports = {
  SCHEMA,
  RULES,
  exactHeaderMatch,
  slugify,
  parseBoolean,
  POPULARITY_LABEL_MAP,
  normalizeBaseStatus,
  normalizePopularity
};